package com.xdxc.factory;


import com.xdxc.annotation.GradingStrategyType;
import com.xdxc.model.enums.AutoGradeQuestionType;
import com.xdxc.exception.BizException;
import com.xdxc.service.strategy.gradingstrategy.GradingStrategy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
public class GradingStrategyFactory implements ApplicationContextAware {

    /**
     * 策略缓存映射
     * Key: QuestionType
     * Value: 策略实例列表（支持多版本策略）
     */
    private final Map<AutoGradeQuestionType, List<GradingStrategy>> strategyMap = new ConcurrentHashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext context) {
        // 获取所有标注@GradingStrategyType的策略Bean
        Map<String, GradingStrategy> strategies = context.getBeansOfType(GradingStrategy.class);

        strategies.forEach((beanName, strategy) -> {
            // 通过反射获取注解信息
            GradingStrategyType annotation = strategy.getClass()
                    .getAnnotation(GradingStrategyType.class);
            if (annotation != null) {
                AutoGradeQuestionType type = annotation.value();
                strategyMap.computeIfAbsent(type, k -> new ArrayList<>())
                        .add(strategy);

                // 按优先级排序
                strategyMap.get(type).sort(Comparator
                        .comparingInt(s -> s.getClass()
                                .getAnnotation(GradingStrategyType.class).priority())
                        .reversed()
                );
            }
        });
    }

    /**
     * 获取批改策略
     * @param type 题型类型
     * @return 匹配的策略实例
     */
    public GradingStrategy getStrategy(AutoGradeQuestionType type) {
        return Optional.ofNullable(strategyMap.get(type))
                .map(list -> {
                    // 优先返回标记为defaultStrategy的策略
                    List<GradingStrategy> defaults = list.stream()
                            .filter(s -> s.getClass()
                                    .getAnnotation(GradingStrategyType.class).defaultStrategy())
                            .collect(Collectors.toList());

                    return !defaults.isEmpty() ? defaults.get(0) : list.get(0);
                })
                .orElseThrow(() -> new BizException("未找到匹配的批改策略: " + type));
    }
}